----------------------------------------------------------------------
-- Bit-serial Processing Element
-- Stephen West, James Carroll
-- BYU ECEn 620, October 2008
--
-- This is almost the top-level; performs bit-serial vector 
-- quantization of digital image data
----------------------------------------------------------------------
Library ieee;
	use ieee.std_logic_1164.all;
	use ieee.numeric_std.all;
	
entity PE is
	generic(
		word_length:integer:=8;
		code_vector_length:integer:=16;
		system_word_length:integer:=12
	);
	port(
			-- Inputs
			clk, config_ctrl_in, index_data, error_in, index_in, lsb_in:in std_logic;
			 pixels_in, config_data :in std_logic_vector(code_vector_length-1 downto 0);
			 -- We might need to change config_data to either 1) use pixels_in or 2) be bit-serial.
			-- Outputs
			 config_ctrl_out, error_out, index_out, lsb_out: out std_logic;
			 pixels_out:out std_logic_vector(code_vector_length-1 downto 0)
	);
end entity;

architecture PE of PE is
	component CodeBook is
		generic(
			word_length:integer:=8;
			code_vector_length:integer:=16;
			system_word_length:integer:=12
		);
		port(
			clk, config_ctrl_in, lsb_in, index_data:in std_logic;
			config_data:in std_logic_vector(code_vector_length-1 downto 0);
			config_ctrl_out, lsb_out, index_bits: out std_logic;
			code_bits: out std_logic_vector(code_vector_length-1 downto 0)
		);
	end component;
	component BitSerialSub16 is
		generic(
			word_length:integer:=8;
			code_vector_length:integer:=16;
			system_word_length:integer:=12
		);
		port(
			clk, lsb_in : in std_logic;
			a_in, b_in : in std_logic_vector(code_vector_length-1 downto 0);
			sub_out : out std_logic_vector(code_vector_length-1 downto 0);
			lsb_out: out std_logic
		);
	end component;
	component BitSerialAbs16 is
		generic(
			word_length:integer:=8;
			code_vector_length:integer:=16;
			system_word_length:integer:=12
		);
		port(
			clk, lsb_in: in std_logic;
			bits_in: in std_logic_vector(code_vector_length-1 downto 0);
			abs_out: out std_logic_vector(code_vector_length-1 downto 0);
			lsb_out: out std_logic
		);
	end component;
	component BitSerialSum16 is
		generic(
			word_length:integer:=8;
			code_vector_length:integer:=16
			--final word length = word_length+log2(code_vector_length)
		);
		port(
			clk, lsb_in:in std_logic;
			a_in: in std_logic_vector(code_vector_length-1 downto 0);
				sum_out, lsb_out: out std_logic
		);
	end component;
	component BitSerialLesser is
		generic(
			word_length:integer:=8;
			code_vector_length:integer:=16;
			system_word_length:integer:=12
		);
		port(
			clk, a_in, b_in, lsb_in:in std_logic;
				lesser_out, a_is_lesser_out, lsb_out: out std_logic
		);
	end component;
	component Delay is
    	generic(
    		delay:integer:=1
    	);
    	port(
    		clk, input :in std_logic;
    		output: out std_logic
    	);
    end component;
	component Delay16 is
		generic(
			delay16:integer:=1;
			word_length:integer:=8;
			code_vector_length:integer:=16;
			system_word_length:integer:=12
		);
		port(
			clk: in std_logic;
			input :in std_logic_vector(code_vector_length-1 downto 0);
			output: out std_logic_vector(code_vector_length-1 downto 0)
		);
	end component;
	signal lsb_internal, sub_lsb,abs_lsb,sum_lsb, sum_out,error_delay,lesser_error,index_this,index_this_delay,index_in_delay, this_is_lesser:std_logic;
	signal code_bits,sub_out,abs_out:std_logic_vector(code_vector_length-1 downto 0);
begin

	delay_pixels:Delay16
		generic map(delay16=>2*system_word_length)
		port map(clk=>clk, input=>pixels_in, output=>pixels_out);
	delay_error:Delay
		generic map(delay=>system_word_length)
		port map(clk=>clk, input=>error_in, output=>error_delay);
	delay_index:Delay
		generic map(delay=>2*system_word_length)
		port map(clk=>clk, input=>index_this, output=>index_this_delay);
	delay_index_in:Delay
		generic map(delay=>2*system_word_length)
		port map(clk=>clk, input=>index_in, output=>index_in_delay);
	code:CodeBook
		port map(
				clk=>clk, config_ctrl_in=>config_ctrl_in, lsb_in=>lsb_in, index_data=>index_data,
				config_data=>config_data, config_ctrl_out=>config_ctrl_out, lsb_out=>lsb_internal,
				code_bits=>code_bits, index_bits=>index_this
				);
	sub16:BitSerialSub16
		port map(clk=>clk, lsb_in=>lsb_in, 
				a_in=>pixels_in, b_in=>code_bits, 
				sub_out=>sub_out, lsb_out=>sub_lsb
				);
	abs16:BitSerialAbs16
		port map(clk=>clk,
				lsb_in=>sub_lsb, bits_in=>sub_out,
				abs_out=>abs_out, lsb_out=>abs_lsb);
	sum16:BitSerialSum16
		port map(clk=>clk, 
				lsb_in=>abs_lsb, a_in=>abs_out,
				sum_out=>sum_out, lsb_out=>sum_lsb
				);
	lesser:BitSerialLesser
		port map(clk=>clk,
				lsb_in=>sum_lsb, a_in=>sum_out, b_in=>error_delay, lsb_out=>lsb_out, lesser_out=>lesser_error, a_is_lesser_out=>this_is_lesser);
	error_out<=lesser_error;
	index_out<=index_this_delay when this_is_lesser='1' else index_in_delay;
	
end architecture;
